#pragma once
#include "../vertex_array.hpp"

namespace opengl {

/* Constructors */
OPENGLAPI vertex_array::vertex_array() : id(0) {} // Do not create the vertex array yet.
OPENGLAPI vertex_array::vertex_array(vertex_array &&other) noexcept : id(other.id) { other.id = 0; }
OPENGLAPI vertex_array::vertex_array(attribute_list attributes) : id(0) { create(attributes); }
OPENGLAPI void vertex_array::create(attribute_list attributes) {
    api::glCreateVertexArrays(1, &id);
    for (const auto &attr : attributes) {
        append_attribute(attr);
    }
}
/* Vertex attributes */
OPENGLAPI void vertex_array::append_attribute(const vertex_attribute &attr) {
    api::glEnableVertexArrayAttrib(id, attr.index);
    api::glVertexArrayAttribBinding(id, attr.index, attr.binding_index);
    api::glVertexArrayAttribFormat(id, attr.index, attr.num_components, attr.type, false, attr.offset);
}
OPENGLAPI void vertex_array::append_attribute(u32 index, u32 type, i32 num_components, u32 offset, u32 binding_index) {
    api::glEnableVertexArrayAttrib(id, index);
    api::glVertexArrayAttribBinding(id, index, binding_index);
    api::glVertexArrayAttribFormat(id, index, num_components, type, false, offset);
}

/* Methods */
OPENGLAPI void vertex_array::bind() const { api::glBindVertexArray(id); }
OPENGLAPI void vertex_array::set_vertex_buffer(const buffer &vertex_buffer, i32 stride, i32 offset,
                                               u32 binding_index) const {
    api::glVertexArrayVertexBuffer(id, binding_index, vertex_buffer.id, offset, stride);
}
OPENGLAPI void vertex_array::set_index_buffer(const buffer &index_buffer) const {
    api::glVertexArrayElementBuffer(id, index_buffer.id);
}

/* Destructors */
OPENGLAPI vertex_array::~vertex_array() {
    if (id != 0) {
        api::glDeleteVertexArrays(1, &id);
    }
}

} // namespace opengl